#!/usr/bin/env python
# -*- coding: utf-8 -*-

class Cell():
    """ Класс описывающий ячейку
    >>> cell = Cell(0, 0)
    >>> cell.set('a')
    >>> cell['letter']
    'a'
    >>> print cell
    a
    >>> print Cell(1, 1, 'b')
    b
    """
    def __init__(self, x, y, letter = None):
        self.can = True
        self.letter = letter
        self.new = False
        self.x = x
        self.y = y
    
    def __repr__(self):
        if isinstance(self.letter, str):
            return str(self.letter)
        else:
            return ""
        
    def __getitem__(self, key):
        if key == 'letter':
            return self.letter
        elif key == 'can':
            return self.can
        elif key == 'new':
            return self.new
        elif key == 'x':
            return self.x
        elif key == 'y':
            return self.y
             
    def set(self, letter):
        self.letter = letter
        self.new = True
        self.can = False
        
    def setCan(self):
        self.can = True
        
    def setOld(self):
        self.new = False
     
        
class Word():
    """ Класс описывающий слово
    >>> word = Word()
    >>> word.append(Cell(0, 0, 'a'))
    >>> word.append(Cell(0, 1, 'j'))
    >>> word.append(Cell(0, 2, 'a'))
    >>> word.append(Cell(0, 3, 'x'))
    >>> print word
    ajax
    >>> word.check()
    True
    """
    def __init__(self):
        self.word = []
        try:
            import sqlite3
            self.conn = sqlite3.connect('words.db')
            self.conn.text_factory = str
            self.c = self.conn.cursor()
        except Exception, e:
            print e
            return 
        
        
    def append(self, letter):
        self.word.append(letter)
        
    def __len__(self):
        return len(self.word)
    
    def __repr__(self):
        def letters():
            for w in self.word:
                yield w.letter
            
        return "".join(letters())
    
    def commit(self):
        for w in self.word:
            w.setOld()

    def check(self):
        self.c.execute(\
            'select * from words where len=:len and word =:word',\
            {"len": self.__len__(), "word": self.__repr__()})
        if self.c.fetchall():
            self.c.close()
            return True
        else:
            self.c.close()
            return False
        
    def isNew(self):
        for w in self.word:
            if w['new']:
                return True
        return False 
    
class Map():
    """ 
    >>> m = Map()
    >>> m.getCell(2, 3)
    <BLANKLINE>
    >>> m.getLetter(0, 0)
    
    >>> m.setLetter(7, 7, 'w')
    >>> m.setLetter(7, 8, 'o')
    >>> m.setLetter(7, 9, 'r')
    >>> m.setLetter(7, 10, 'l')
    >>> m.setLetter(7, 11, 'd')
    >>> m.getLetter(7, 7)
    'w'
    >>> m.isNew(7, 7)
    True
    >>> m.isNew(1, 0)
    False
    >>> m.setLetter(7, 8, 'o')
    >>> m.setLetter(8, 8, 's')
    >>> m.setLetter(9, 8, 'l')
    >>> m.setLetter(10, 8, 'o')
    >>> m.setLetter(7, 11, 'd')
    >>> m.setLetter(8, 11, 'o')
    >>> m.setLetter(9, 11, 'o')
    >>> m.setLetter(10, 11, 'r')
    >>> w = m.findWords()
    >>> print w
    [world, oslo, door]
    >>> w[0].commit()
    >>> m.findNewWords()
    [oslo, door]
    """
    def __init__(self, size=15):
        self.size = size
        self.m = [[Cell(x, y) \
                   for y in range(self.size)] \
                   for x in range(self.size)]
        self.m[self.size // 2][self.size // 2].setCan()

    def getCell(self, x, y):
        return self.m[x][y]
        
    def getLetter(self, x, y):
        return self.m[x][y]['letter']
        
    def setLetter(self, x, y, letter):
        if self.m[x][y]['can']:
            self.m[x][y].set(letter)
        
    def isNew(self, x, y):
        return self.m[x][y]['new']
    
    def findWords(self):
        """requires optimization"""
        words = []
        for x in range(self.size):
            word = Word()
            for y in range(self.size):
                if self.m[x][y]['letter']:
                    word.append(self.m[x][y])
                else:
                    if len(word) > 2:
                        words.append(word)
                        word = []
        # requires optimization
        for y in range(self.size):
            word = Word()
            for x in range(self.size):
                if self.m[x][y]['letter']:
                    word.append(self.m[x][y])
                else:
                    if len(word) > 2:
                        words.append(word)
                        word = []
        return words
    
    def findNewWords(self):
        new_words = []
        words = self.findWords()
        for w in words:
            if w.isNew():
                new_words.append(w)
        return new_words

import random

class Alphabet(object):
    """класс содержит набор возможных букв
    >>> a = Alphabet()
    >>> a.get()
    
    >>> len(a)
    102
    >>> a.get()
    
    >>> len(a)
    101
    """
    _instance = None
    def __new__(self, *args, **kwargs):
        if not self._instance:
            self._instance = \
                super(Alphabet, self).__new__(self, *args, **kwargs)
        return self._instance
         
    def __init__(self):
        self.alphabet = []
        try:
            import sqlite3
            self.conn = sqlite3.connect('words.db')
            self.conn.text_factory = str
            self.c = self.conn.cursor()
        except Exception, e:
            print e
            return 
        self.readAlphabet()
        
    def __len__(self):
        return len(self.alphabet)
    
    def readAlphabet(self):
        self.c.execute('select * from alphabet')
        for row in self.c.fetchall():
            for i in range(row[1]):
                self.alphabet.append({\
                    'l':row[0].decode("utf-8"), 'cost': row[2]})
        
    def get(self):
        ind = random.randint(0, len(self))
        value = self.alphabet[ind]
        self.alphabet.pop(ind)
        return value
    
    def push(self):
        pass

if __name__ == '__main__':
    import doctest
    doctest.testmod()